import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

public class Bootstrap {
    public static final String CONFIG_FILE = "/opt/rjfile/bin/Bootstrap.conf";
    //KILL 进程的关键字
    public static final String KILL_WORD = "rjfile.jar";

    public static void main(String[] args) throws IOException, InterruptedException {
        if(args.length  == 0){
            printHelp();
            return;
        }
        String arg0 = args[0];
        switch (arg0){
            case "start":
                start();
                break;
            case "stop":
                stop();
                break;
            case "restart":
                stop();
                start();
                break;
            case "status":
                status();
                break;
            case "-h":
                printHelp();
                break;
            case "-v":
                version();
                break;
            default:
                printTips();
        }
    }

    public static boolean checkConf() throws IOException {
        Properties prop = getProp();
        String port = prop.getProperty("port");
        if(isBlank(port)){
            print("!!! 配置文件" + CONFIG_FILE + "没有配置port");
            return false;
        }
        String cmd = prop.getProperty("cmd");
        if(isBlank(cmd)){
            print("!!! 配置文件" + CONFIG_FILE + "没有配置cmd");
            return false;
        }
        return true;
    }

    public static boolean isBlank(String str){
        return str == null || str.trim().isEmpty();
    }

    public static void version() throws IOException, InterruptedException{
        if(!checkConf()) return;
        Properties prop = getProp();
        JSONObject result = testGetInfo(prop.getProperty("port"));
        print("==========");
        print("版本：" + result.getString("version"));
    }

    public static void status() throws IOException, InterruptedException {
        if(!checkConf()) return;
        Properties prop = getProp();
        JSONObject result = testGetInfo(prop.getProperty("port"));
        showResult(result);
    }


    public static void stop() throws IOException, InterruptedException {
        if(!checkConf()) return;
        Properties prop = getProp();
        String port = prop.getProperty("port");

        String[] cmd = { "/bin/sh", "-c", "kill $(ps -aef | grep " + KILL_WORD + " | grep -v grep | awk '{print $2}')" };
        String[] cmd_9 = { "/bin/sh", "-c", "kill -9 $(ps -aef | grep " + KILL_WORD + " | grep -v grep | awk '{print $2}')" };
        run(cmd);
        TimeUnit.SECONDS.sleep(1);
        run(cmd_9);
        TimeUnit.SECONDS.sleep(1);
    }
    public static void start () throws IOException, InterruptedException {
        if(!checkConf()) return;
        //1 取配置文件
        Properties prop = getProp();

        String port = prop.getProperty("port");
        String cmd = prop.getProperty("cmd");

        if(cmd != null) {
            run(cmd);
        } else {
            print("ERROR " + CONFIG_FILE + " 没有配置cmd命令");
            return;
        }

        int i=1;
        String c;
        while(( c =  prop.getProperty("cmd" + i) ) != null){
            run(c);
            i++;
        }

        //check the server
        print("服务正在启动, 请稍等几秒钟（等待30秒）......");

        JSONObject result = testGetInfo(port, true);
        showResult(result);

    }
    public static void showResult(JSONObject jsonObject){
        boolean result = (Boolean)jsonObject.get("result");
        print("==========");
        if(result){
            print("服务状态：正常");
        } else {
            print("服务状态：异常！！！");
        }
        print(jsonObject.getString("msg"));
        print("版本：" + jsonObject.getString("version"));
    }
    public static void printHelp(){
        print("========== HELP ==========");
        print("用法: rjfile [start] [stop] [restart] [status]  [-v] [-h]");
        print();
        print("\t rjfile start : 启动rjfile");
        print("\t rjfile stop : 停止rjfile");
        print("\t rjfile restart : 重启rjfile");
        print("\t rjfile status : 查看文件状态");
        print("\t rjfile -v : 查看rjfile服务端版本");
        print("\t rjfile -h : 帮助");
    }

    public static void printTips(){
        print("========== 没找到相关命令 ==========");
        print("用法: rjfile [start] [stop] [restart] [status] [-v] [-h]");
        print("试用 rjfile -h'来获得更多信息。");
    }

    public static Properties getProp() throws IOException {
        //1 取配置文件
        Path path = Paths.get(CONFIG_FILE);
        Properties prop = new Properties();
        prop.load(Files.newInputStream(path));
        return prop;
    }

    public static void run(String cmd) throws IOException {
        String [] cmdLast = new String[]{"/bin/sh", "-c", cmd};
        run(cmdLast);
    }
    public static void run(String[] cmd) throws IOException {
        System.out.print("运行命令: ");
        for(String s : cmd){
            System.out.print(s + " ");
        }
        print();
        Runtime.getRuntime().exec(cmd);
    }

    public static void print(String s){
        System.out.println(s);
    }
    public static void print(){
        System.out.println();
    }

    public static JSONObject testGetInfo(String port) throws IOException, InterruptedException {
        return testGetInfo(port, false);
    }
    public static JSONObject testGetInfo(String port, boolean times) throws IOException, InterruptedException {
        String urlStr = "http://localhost:"+ port +"/rjfile/info";
        print("checking...... " + urlStr);
        if(times){
            //每500ms 检查一次，30秒后超时
            int count = 60;
            while (count > 0){
                try{
                    String s = getInfo(urlStr);
                    return JSON.parseObject(s);
                }catch (Exception e){
                    //ignore
                }
                TimeUnit.MILLISECONDS.sleep(500);
                count--;
            }
        }
        try {
            String s = getInfo(urlStr);
            return JSON.parseObject(s);
        } catch (SocketTimeoutException timeoutException){
            print("+----------------------------------------------+");
            print("|ERROR:文件服务没启动,访问超时! 请查看rjfile/logs日志|");
            print("+----------------------------------------------+");
            throw timeoutException;
        } catch (ConnectException connectException){
            print("+------------------------------------------------------------+");
            print("|ERROR:文件服务没启动，无法方法文件服务web端！  请查看rjfile/logs日志|");
            print("+------------------------------------------------------------+");
            throw connectException;
        }
    }
    public static String getInfo(String urlStr) throws IOException {
        URL url = new URL(urlStr);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("GET");

        con.setConnectTimeout(8000);
        con.setReadTimeout(8000);
        int status = con.getResponseCode();
        BufferedReader streamReader;

        if (status > 299) {
            streamReader = new BufferedReader(new InputStreamReader(con.getErrorStream()));
        } else {
            streamReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
        }

        String inputLine;
        StringBuilder content = new StringBuilder();
        while ((inputLine = streamReader.readLine()) != null) {
            content.append(inputLine);
        }

        streamReader.close();
        con.disconnect();
        return content.toString();
    }
}